#!/bin/bash
# Copyright 2012 Google, Inc. All rights reserved.

# This script provides a simple way to run benchmarks against previous code and
# keep a log of how benchmarks change over time.  When used with the --benchmark
# flag, it runs benchmarks from the current code and from the last commit run
# with --benchmark, then stores the results in the git commit description.  We
# rerun the old benchmarks along with the new ones, since there's no guarantee
# that git commits will happen on the same machine, so machine differences could
# cause wildly inaccurate results.
#
# If you're making changes to 'gopacket' which could cause performance changes,
# you may be requested to use this commit script to make sure your changes don't
# have large detrimental effects (or to show off how awesome your performance
# improvements are).
#
# If not run with the --benchmark flag, this script is still very useful... it
# makes sure all the correct go formatting, building, and testing work as
# expected.

function Usage {
  echo "USAGE:  $0 [--benchmark] [--gen] <git commit flags...>"
  echo
  echo "Note, some 'git commit' flags are necessary, if all else fails, pass in -a"
  exit 1
}

BENCH=""
GEN=""
while [ ! -z "$1" ]; do
  case "$1" in
    "--benchmark")
      BENCH="yes"
      shift
      ;;
    "--gen")
      GEN="yes"
      shift
      ;;
    "--help")
      Usage
      ;;
    "-h")
      Usage
      ;;
    "help")
      Usage
      ;;
    *)
      break
      ;;
  esac
done

if [ "$#" -eq "0" ]; then
  Usage
fi

set -e
set -x

cd $(dirname $0)

if [ ! -z "$GEN" ]; then
  go run gen.go | gofmt > valid_mac_prefixes.go
	pushd layers
	go run gen.go | gofmt > iana_ports.go
	popd
fi

# First, make sure everything is formatted, compiles, and tests pass.
go fmt ./...
gofmt -w gen.go
go build gen.go
go test -i ./... 2>/dev/null >/dev/null || true
go test
go build
pushd layers
gofmt -w gen.go
go build gen.go
go test
popd
if [ -f /usr/include/pcap.h ]; then
	pushd pcap
	go test ./...
  go build ./...
	popd
fi
if [ -f /usr/include/pfring.h ]; then
	pushd pfring
	go test ./...
  go build ./...
	popd
fi

# Run our initial commit
git commit "$@"

if [ -z "$BENCH" ]; then
  set +x
  echo "We're not benchmarking and we've committed... we're done!"
  exit
fi

### If we get here, we want to run benchmarks from current commit, and compare
### then to benchmarks from the last --benchmark commit.

# Get our current branch.
BRANCH="$(git branch | grep '^*' | awk '{print $2}')"

# File we're going to build our commit description in.
COMMIT_FILE="$(mktemp /tmp/tmp.XXXXXXXX)"

# Add the word "BENCH" to the start of the git commit.
echo -n "BENCH " > $COMMIT_FILE

# Get the current description... there must be an easier way.
git log -n 1 | grep '^ ' | sed 's/^    //' >> $COMMIT_FILE

# Get the commit sha for the last benchmark commit
PREV=$(git log -n 1 --grep='BENCHMARK_MARKER_DO_NOT_CHANGE' | head -n 1 | awk '{print $2}')

## Run current benchmarks

cat >> $COMMIT_FILE <<EOF


----------------------------------------------------------
BENCHMARK_MARKER_DO_NOT_CHANGE
----------------------------------------------------------

Go version $(go version)


TEST BENCHMARKS
EOF
go test ./... --test.bench=.* 2>&1 | tee -a $COMMIT_FILE
cat >> $COMMIT_FILE <<EOF


PCAP BENCHMARK
EOF
go run pcap/gopacket_benchmark/*.go 2>&1 | tee -a $COMMIT_FILE



## Reset to last benchmark commit, run benchmarks

git checkout $PREV

cat >> $COMMIT_FILE <<EOF
----------------------------------------------------------
BENCHMARKING AGAINST COMMIT $PREV
----------------------------------------------------------


OLD TEST BENCHMARKS
EOF
go test ./... --test.bench=.* 2>&1 | tee -a $COMMIT_FILE
cat >> $COMMIT_FILE <<EOF


OLD PCAP BENCHMARK
EOF
go run pcap/gopacket_benchmark/*.go 2>&1 | tee -a $COMMIT_FILE



## Reset back to the most recent commit, edit the commit message by appending
## benchmark results.
git checkout $BRANCH
git commit --amend -F $COMMIT_FILE
